package nachos.network;
import java.util.logging.Level;
import java.util.logging.Logger;
import nachos.machine.*;
/**
 * A mail message. Includes a packet header, a mail header, and the actual
 * payload.
 *
 * @see	nachos.machine.Packet
 */
public class MailMessage {
	public static void main(String args[]){
		try {
			System.out.println("--");
			MailMessage msg = new MailMessage(1, 2, 3, 4, 5, new byte[0], false, true, true, true);
			System.out.println("--");
			MailMessage msg2 = new MailMessage(msg.packet);
			System.out.println(msg2);
		} catch (MalformedPacketException ex) {
			System.out.println("fuck");
		}
	}
	/**
	 * Allocate a new mail message to be sent, using the specified parameters.
	 *
	 * @param	dstLink		the destination link address.
	 * @param	dstPort		the destination port.
	 * @param	srcLink		the source link address.
	 * @param	srcPort		the source port.
	 * @param	contents	the contents of the packet.
	 */
	//syn ack
	//fin
	//int number packet number....
	public MailMessage(int dstLink, int dstPort, int srcLink, int srcPort, int con_id,
		byte[] contents, boolean syn, boolean ack, boolean fin, boolean packetTogle) throws MalformedPacketException{
		// make sure the paramters are valid
		if(dstPort < 0 || dstPort >= portLimit
			|| srcPort < 0 || srcPort >= portLimit
			|| contents.length > maxContentsLength
			|| (syn & ack & fin)){
			Lib.debug('l', "Failing data: " + dstPort + " " + srcPort + " " + contents.length);
			throw new MalformedPacketException();
		}

		//set this messages values
		this.dstPort = (byte) dstPort;
		this.srcPort = (byte) srcPort;
		this.connectionid = (byte) con_id;
		this.contents = new byte[contents.length];
		this.syn = syn;
		this.ack = ack;
		this.fin = fin;
		this.posToggle = packetTogle;
		System.arraycopy(contents, 0, this.contents, 0,
			contents.length);

		//new array to be put into packet
		byte[] packetContents = new byte[headerLength + contents.length];

		//attatch this messages header
		packetContents[0] = (byte) dstPort;
		packetContents[1] = (byte) srcPort;
		packetContents[connidPos] = (byte) con_id;

		packetContents[synPos] = 0;
		if(syn) packetContents[synPos] += 0x1;
		if(fin) packetContents[finPos] += 0x2;
		if(ack) packetContents[ackPos] += 0x4;
		if(packetTogle) packetContents[ptogPos] += 0x8;
		//and thena atttch the contents
		System.arraycopy(contents, 0, packetContents, headerLength,
			contents.length);
		packet = new Packet(dstLink, srcLink, packetContents);
	}
	/**
	 * Allocate a new mail message using the specified packet from the network.
	 *
	 * @param	packet	the packet containing the mail message.
	 */
	public MailMessage(Packet packet) throws MalformedPacketException{
		this.packet = packet;

		// make sure we have a valid header
		if(packet.contents.length < headerLength
			|| packet.contents[0] < 0 || packet.contents[0] >= portLimit
			|| packet.contents[1] < 0 || packet.contents[1] >= portLimit){
			throw new MalformedPacketException();
		}

		dstPort = packet.contents[0];
		srcPort = packet.contents[1];
		connectionid = packet.contents[connidPos];
		syn = ((packet.contents[synPos] & 0x1) == 0x1);//0001 & 0110 = 0000
		fin = ((packet.contents[finPos] & 0x2) == 0x2);//0010 & 0110 = 0010
		ack = ((packet.contents[ackPos] & 0x4) == 0x4);//0100 & 0110 = 0100
		posToggle = ((packet.contents[ptogPos] & 0x8) == 0x8);

		contents = new byte[packet.contents.length - headerLength];
		System.arraycopy(packet.contents, headerLength, contents, 0,
			contents.length);
	}
	/**
	 * Return a string representation of the message headers.
	 */
	public String toString(){
		String str = "from (" + packet.srcLink + ":" + srcPort
			+ ") to (" + packet.dstLink + ":" + dstPort
			+ "), at conid " + connectionid + " mlength: " + contents.length + " bytes";
		if(syn){
			str += " Syn";
		}
		if(fin){
			str += " Fin";
		}
		if(ack){
			str += " Ack";
		}
		if(posToggle){
			str += " Toggled";
		}
		return str;
	}
	/** This message, as a packet that can be sent through a network link. */
	public Packet packet;
	/** The port used by this message on the destination machine. */
	public int dstPort;
	/** The port used by this message on the source machine. */
	public int srcPort;
	/** The contents of this message, excluding the mail message header. */
	public byte[] contents;
	//my flags 'n shit
	public boolean syn;
	public boolean ack;
	public boolean fin;
	public boolean posToggle;
	public int connectionid;
	//static markers!
	private static final int synPos = 2;
	private static final int ackPos = 2;
	private static final int finPos = 2;
	private static final int ptogPos = 2;
	private static final int connidPos = 3;
	public static final int headerLength = 4;
	/** Maximum payload (real data) that can be included in a single message. */
	public static final int maxContentsLength = Packet.maxContentsLength - headerLength;
	/**
	 * The upper limit on mail ports. All ports fall between <tt>0</tt> and
	 * <tt>portLimit - 1</tt>.
	 */
	public static final int portLimit = 128;
}
